package com.cyx.spring.io;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;

import java.util.*;
import java.util.function.Function;

/**
 * PropertyResolver
 * ${com.another.property:defaultValue}
 *
 * @author yongxiang
 * @date 2024/10/18 15:08
 * @desc
 */
public class PropertyResolver {

    //类型转化convertMap
    public Map<Class<?>, Function<String,Object>> convertMap = new HashMap<>();

    private Map<String, String> propertiesMap = new HashMap<>();


    public PropertyResolver(Properties properties) {
        propertiesMap.putAll(System.getenv());
        if (properties != null && !properties.isEmpty()) {
            Set<String> keys = properties.stringPropertyNames();
            for (String key : keys) {
                propertiesMap.put(key, properties.getProperty(key));
            }
        }
        this.addDefaultConvert();
    }

    public<T> T getProperty(String key, Class<T> targetClass) {
        Assert.notNull(targetClass, "Property type must not be null");
        String value = getProperty(key);
        if (value == null) {
            return null;
        }
        Function<String, Object> convert = convertMap.get(targetClass);
        if (convert == null){
             throw new IllegalStateException("Property type '" + targetClass.getName() + "' is not supported");
        }
        return (T) convert.apply(value);
    }


    public void addDefaultConvert() {
        convertMap.put(String.class,  s -> s);
        convertMap.put(Integer.class,  Integer::valueOf);
        convertMap.put(Long.class, Long::valueOf);
        convertMap.put(Double.class, Double::valueOf);
        convertMap.put(Boolean.class,  Boolean::valueOf);
        convertMap.put(Float.class,  Float::valueOf);
        convertMap.put(Date.class, DateUtil::parse);
    }

    public String getProperty(String key) {
        Assert.notNull(key, "Property name must not be null");
        //解析key
        PropertyExpr propertyExpr = resolverKey(key);
        String defaultValue = propertyExpr.defaultValue();
        String value = propertiesMap.get(propertyExpr.key());
        if (defaultValue == null) {
            if (value == null) {
                throw new IllegalStateException("Property '" + key + "' has not been set");
            }
        }
        return value == null ? defaultValue : value;

    }

    private PropertyExpr resolverKey(String key) {
        if (key.startsWith("${") && key.endsWith("}")) {
            key = key.substring(2, key.length() - 1);
            if (key.contains(":")) {
                int index = key.indexOf(":");
                String reKey = key.substring(0, index);
                String defaultValue = key.substring(index + 1);
                return new PropertyExpr(reKey, defaultValue);
            }
        }
        return new PropertyExpr(key, null);

    }


}
